home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / aztecnos.arc / PKTDRVR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-18  |  8.7 KB  |  378 lines

  1. /* Driver for FTP Software's packet driver interface */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "proc.h"
  5. #include "mbuf.h"
  6. #include "enet.h"
  7. #include "ax25.h"
  8. #include "slip.h"
  9. #include "kiss.h"
  10. #include "iface.h"
  11. #include "ec.h"
  12. #include "timer.h"
  13. #include "arp.h"
  14. #include "trace.h"
  15. #include "regs.h"
  16. #include "pktdrvr.h"
  17. #include "config.h"
  18.  
  19. extern struct mbuf *Hopper;
  20. void pkvec(),pkint();
  21. void (*getvect())();
  22. static int access_type(),release_type(),send_pkt(),get_address();
  23. #ifdef    notdef
  24. static int driver_info();
  25. #endif
  26.  
  27. struct pktdrvr Pktdrvr[PK_MAX];
  28. unsigned int Npk;
  29. int Derr;
  30.  
  31. /* Send raw packet (caller provides header) */
  32. int
  33. pk_raw(iface,bp)
  34. struct iface *iface;    /* Pointer to interface control block */
  35. struct mbuf *bp;    /* Data field */
  36. {
  37.     register struct pktdrvr *pp;
  38.     int16 size;
  39.     struct mbuf *bp1;
  40.  
  41.     pp = &Pktdrvr[iface->dev];
  42.     size = len_mbuf(bp);
  43.  
  44.     switch(pp->class){
  45.     case CL_ETHERNET:
  46.         dump(iface,IF_TRACE_OUT,TYPE_ETHER,bp);
  47.         if(size < 60)
  48.             size = 60;
  49.         break;
  50.     case CL_SERIAL_LINE:
  51.         dump(iface,IF_TRACE_OUT,TYPE_IP,bp);
  52.         break;
  53.     case CL_AX25:
  54.         dump(iface,IF_TRACE_OUT,TYPE_AX25,bp);
  55.         break;
  56.     case CL_KISS:
  57.         dump(iface,IF_TRACE_OUT,TYPE_AX25,bp);
  58.         /* This *really* shouldn't be done here, but it was the
  59.          * easiest way. Put the type field for KISS TNC on front.
  60.          */
  61.         if((bp1 = pushdown(bp,1)) == NULLBUF){
  62.             free_p(bp);
  63.             return -1;
  64.         }
  65.         bp = bp1;
  66.         bp->data[0] = KISS_DATA;
  67.         break;
  68.     }
  69.     if(bp->next != NULLBUF){
  70.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  71.         bp1 = copy_p(bp,size);
  72.         free_p(bp);
  73.         bp = bp1;
  74.         if(bp == NULLBUF)
  75.             return -1;
  76.     } else
  77.         bp->cnt = size;    /* Make sure packet size is big enough */
  78.  
  79.     send_pkt(pp->intno,bp->data,bp->cnt);
  80.     free_p(bp);
  81.     return 0;
  82. }
  83.  
  84. /* Packet driver receive routine. Called from an assembler hook that pushes
  85.  * the caller's registers on the stack so we can access and modify them.
  86.  * This is a rare example of call-by-location in C.
  87.  */
  88. void
  89. pkint(di,si,bp,dx,cx,bx,ax,ds,es)
  90. unsigned short di,si,bp,dx,cx,bx,ax,ds,es;
  91. {
  92.     register struct pktdrvr *pp;
  93.     int i;
  94.     struct phdr *phdr;
  95.  
  96.     for(i=0,pp = &Pktdrvr[0];i < Npk;i++,pp++)
  97.         if(pp->handle1 == bx
  98.          || (pp->class == CL_ETHERNET && pp->handle2 == bx))
  99.             break;
  100.     if(i == Npk)
  101.         return;    /* Unknown packet */
  102.  
  103.     switch(ax){
  104.     case 0:    /* Space allocate call */
  105.         if(pp->rcvcnt < pp->rcvmax &&
  106.          (pp->buffer = alloc_mbuf(cx+sizeof(struct phdr))) != NULLBUF){
  107.             es = FP_SEG(pp->buffer->data);
  108.             di = FP_OFF(pp->buffer->data+sizeof(struct phdr));
  109.             pp->buffer->cnt = cx + sizeof(struct phdr);
  110.             phdr = (struct phdr *)pp->buffer->data;
  111.             phdr->iface = pp->iface;
  112.             switch(pp->class){
  113.             case CL_ETHERNET:
  114.                 phdr->type = TYPE_ETHER;
  115.                 break;
  116.             case CL_SERIAL_LINE:
  117.                 phdr->type = TYPE_IP;
  118.                 break;
  119.             case CL_AX25:
  120.                 phdr->type = TYPE_AX25;
  121.                 break;
  122.             case CL_KISS:
  123.                 phdr->type = TYPE_KISS;
  124.                 break;
  125.             }
  126.         } else {
  127.             es = di = 0;
  128.         }
  129.         break;
  130.     case 1:    /* Packet complete call */
  131.         enqueue(&Hopper,pp->buffer);
  132.         pp->buffer = NULLBUF;
  133.         break;
  134.     default:
  135.         break;
  136.     }
  137. }
  138.  
  139. /* Shut down the packet interface */
  140. pk_stop(iface)
  141. struct iface *iface;
  142. {
  143.     struct pktdrvr *pp;
  144.  
  145.     pp = &Pktdrvr[iface->dev];
  146.     /* Call driver's release_type() entry */
  147.     if(release_type(pp->intno,pp->handle1) == -1)
  148.         printf("%s: release_type error code %u\n",iface->name,Derr);
  149.  
  150.     if(pp->class == CL_ETHERNET)
  151.         release_type(pp->intno,pp->handle2);
  152. }
  153. /* Attach a packet driver to the system
  154.  * argv[0]: hardware type, must be "packet"
  155.  * argv[1]: software interrupt vector, e.g., x7e
  156.  * argv[2]: interface label, e.g., "trw0"
  157.  * argv[3]: maximum number of packets allowed on receive queue, e.g., "5"
  158.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  159.  */
  160. int
  161. pk_attach(argc,argv)
  162. int argc;
  163. char *argv[];
  164. {
  165.     register struct iface *if_pk;
  166.     int class;
  167.     unsigned int intno;
  168.     static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  169.     static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  170.     long drvvec;
  171.     char sig[8];    /* Copy of driver signature "PKT DRVR" */
  172.     register struct pktdrvr *pp;
  173.  
  174.     if(Npk >= PK_MAX){
  175.         printf("Too many packet drivers\n");
  176.         return -1;
  177.     }
  178.     if(if_lookup(argv[2]) != NULLIF){
  179.         printf("Interface %s already exists\n",argv[2]);
  180.         return -1;
  181.     }
  182.  
  183.     intno = htoi(argv[1]);
  184.     /* Verify that there's really a packet driver there, so we don't
  185.      * go off into the ozone (if there's any left)
  186.      */
  187.     drvvec = (long)getvect(intno);
  188.     movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  189.         FP_OFF(sig),FP_SEG(sig),strlen(PKT_SIG));
  190.     if(strncmp(sig,PKT_SIG,strlen(PKT_SIG)) != 0){
  191.         printf("No packet driver loaded at int 0x%x\n",intno);
  192.         return -1;
  193.     }
  194.     if((if_pk = (struct iface *)calloc(1,sizeof(struct iface))) == NULLIF
  195.      ||(if_pk->name = strdup(argv[2])) == NULLCHAR){
  196.         if(if_pk != NULLIF)
  197.             free((char *)if_pk);
  198.         printf("pk_attach: no memory!\n");
  199.         return -1;
  200.     }
  201.     pp = &Pktdrvr[Npk];
  202.     pp->rcvmax = atoi(argv[3]);
  203.     if_pk->mtu = atoi(argv[4]);
  204.     if_pk->dev = Npk++;
  205.     if_pk->raw = pk_raw;
  206.     if_pk->stop = pk_stop;
  207.     pp->intno = intno;
  208.     pp->iface = if_pk;
  209.  
  210.     /* Find out by exhaustive search what class this driver is (ugh) */
  211.     for(class=0;class<9;class++){
  212.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,pkvec);
  213.         if(pp->handle1 != -1)
  214.             break;
  215.     }
  216.     /* Now that we know, release it and do it all over again with the
  217.      * right type fields
  218.      */
  219.     release_type(intno,pp->handle1);
  220.     switch(class){
  221.     case CL_ETHERNET:
  222.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,pkvec);
  223.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,pkvec);            
  224.         if_pk->send = enet_send;
  225.         if_pk->output = enet_output;
  226.         /* Get hardware Ethernet address from driver */
  227.         if((if_pk->hwaddr = malloc(EADDR_LEN)) == NULLCHAR){
  228.             free(if_pk->name);
  229.             free((char *)if_pk);
  230.             printf("pk_attach: no memory!\n");
  231.             return -1;
  232.         }
  233.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  234.         arp_init(ARP_ETHER,EADDR_LEN,IP_TYPE,ARP_TYPE,1,Ether_bdcst,pether,gaether);
  235.         break;
  236.     case CL_SERIAL_LINE:
  237.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,pkvec);
  238.         if_pk->send = slip_send;
  239.         break;
  240. #ifdef    KISS
  241.     case CL_KISS:    /* Note that the raw routine puts on the command */
  242.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,pkvec);
  243.         if_pk->send = ax_send;
  244.         if_pk->output = ax_output;
  245.         break;
  246. #endif
  247. #ifdef    AX25
  248.     case CL_AX25:
  249.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,pkvec);
  250.         if_pk->send = ax_send;
  251.         if_pk->output = ax_output;
  252.         break;
  253. #endif
  254.     default:
  255.         printf("Packet driver has unsupported class %u\n",class);
  256.         free(if_pk->name);
  257.         free((char *)if_pk);
  258.         Npk--;
  259.         return -1;
  260.     }
  261.     pp->class = class;
  262.     if_pk->next = Ifaces;
  263.     Ifaces = if_pk;
  264.  
  265.     return 0;
  266. }
  267. static int
  268. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  269. int intno;
  270. int if_class;
  271. int if_type;
  272. int if_number;
  273. char *type;
  274. unsigned typelen;
  275. void (*receiver)();
  276. {
  277.     struct regs regs;
  278.  
  279.     _DL = if_number;        /* Number */
  280.     /* Packet type template */
  281.     _DS = FP_SEG(type);
  282.     _SI = FP_OFF(type);
  283.     _CX = typelen;            /* Length of type */
  284.     /* Address of receive handler */
  285.     _ES = FP_SEG(receiver);
  286.     _DI = FP_OFF(receiver);
  287.     _BX = if_type;            /* Type */
  288.     _AH = ACCESS_TYPE;    /* Access_type() function */
  289.     _AL = if_class;        /* Class */
  290.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  291.         Derr = _DH;
  292.         return -1;
  293.     } else
  294.         return _AX;
  295. }
  296. static int
  297. release_type(intno,handle)
  298. int intno;
  299. int handle;
  300. {
  301.     struct regs regs;
  302.  
  303.     _BX = handle;
  304.     _AH = RELEASE_TYPE;
  305.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  306.         Derr = _DH;
  307.         return -1;
  308.     } else
  309.         return 0;
  310. }
  311. static int
  312. send_pkt(intno,buffer,length)
  313. int intno;
  314. char *buffer;
  315. unsigned length;
  316. {
  317.     struct regs regs;
  318.  
  319.     _DS = FP_SEG(buffer);
  320.     _SI = FP_OFF(buffer);
  321.     _CX = length;
  322.     _AH = SEND_PKT;
  323.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  324.         Derr = _DH;
  325.         return -1;
  326.     } else
  327.         return 0;
  328. }
  329. #ifdef    notdef
  330. static int
  331. driver_info(intno,handle,version,class,type,number,basic)
  332. int intno;
  333. int handle;
  334. int *version,*class,*type,*number,*basic;
  335. {
  336.     struct regs regs;
  337.  
  338.     _BX = handle;
  339.     _AH = DRIVER_INFO;
  340.     _AL = 0xff;
  341.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  342.         Derr = _DH;
  343.         return -1;
  344.     }
  345.     if(version != NULL)
  346.         *version = _BX;
  347.     if(class != NULL)
  348.         *class = _CH;
  349.     if(type != NULL)
  350.         *type = _DX;
  351.     if(number != NULL)
  352.         *number = _CL;
  353.     if(basic != NULL)
  354.         *basic = _AL;
  355.     return 0;
  356. }
  357. #endif
  358. static int
  359. get_address(intno,handle,buf,len)
  360. int intno;
  361. int handle;
  362. char *buf;
  363. int len;
  364. {
  365.     struct regs regs;
  366.  
  367.     _ES = FP_SEG(buf);
  368.     _DI = FP_OFF(buf);
  369.     _CX = len;
  370.     _BX = handle;
  371.     _AH = GET_ADDRESS;
  372.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  373.         Derr = _DH;
  374.         return -1;
  375.     }
  376.     return 0;
  377. }
  378.